/*
 * Copyright (C) 2022, KylinSoft Co., Ltd.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 *
 */

#include "wifi-shortcut.h"

#include <QDebug>
#include <QProcess>
#include <QDBusReply>
#include <QDBusMessage>
#include <QDBusConnection>
#include <QApplication>
#include <QTranslator>

using namespace UkuiShortcut;

UkuiShortcut::WiFiShortcut::WiFiShortcut(QObject *parent) : Shortcut(parent)
{
    initMetaData();
    initMemberVariables();
    networkDbus();
    getUsedWIFIConnections();
    initNetworkManagerConnect();
    getButtonState();
}

WiFiShortcut::~WiFiShortcut()
{   
    if (m_wifiDbusThread) {
        m_wifiDbusThread->quit();
        m_wifiDbusThread->wait();
        delete m_wifiDbusThread;
    }
    if (m_wifiDbusQuery) {
        delete m_wifiDbusQuery;
    }
}

//翻译，插件信息初始化
void WiFiShortcut::initMemberVariables()
{
    m_wifiDbusThread = new QThread();
    m_wifiDbusQuery = new WifiDbusQuery();
    m_wifiDbusThread->start();
    m_wifiDbusQuery->moveToThread(m_wifiDbusThread);
    connect(this, &WiFiShortcut::toQueryDevice, m_wifiDbusQuery, &WifiDbusQuery::isWirelessDeviceEnabled);
    connect(m_wifiDbusQuery, &WifiDbusQuery::deviceQuery, this, &WiFiShortcut::handleDeviceQuery);
    connect(this, &WiFiShortcut::toQueryUsedWifiConnect, m_wifiDbusQuery, &WifiDbusQuery::queryUsedWifiConnect);
    connect(m_wifiDbusQuery, &WifiDbusQuery::usedWifiName, this, &WiFiShortcut::handleUsedWifiConnect);

    m_currentStatus.setName(tr("WiFi"));
    m_currentStatus.setIcon(KYLIN_WIFI_PATH);
    m_currentStatus.setToolTip(tr("WiFi"));

    Q_EMIT toQueryDevice();
}

//信号连接
void WiFiShortcut::initNetworkManagerConnect()
{
    QDBusConnection::systemBus().connect( NETWORK_MANAGER_NAME,
                                          NETWORK_MANAGER_PATH,
                                          NETWORK_DBUS_PROPERTIES_INTERFACE,
                                          "PropertiesChanged", this, SLOT(onPropertiesChanged(QString, QVariantMap)));

    QDBusConnection::systemBus().connect( NETWORK_MANAGER_NAME,
                                          NETWORK_MANAGER_PATH,
                                          NETWORK_MANAGER_INTERFACE,
                                          "DeviceAdded", this, SLOT(onDevicestatusChanged()));

    QDBusConnection::systemBus().connect( NETWORK_MANAGER_NAME,
                                          NETWORK_MANAGER_PATH,
                                          NETWORK_MANAGER_INTERFACE,
                                          "DeviceRemoved", this, SLOT(onDevicestatusChanged()));
}

void WiFiShortcut::networkDbus()
{
    m_networkDbusInterface = new QDBusInterface( NETWORK_MANAGER_NAME,
                                                 NETWORK_MANAGER_PATH,
                                                 NETWORK_DBUS_PROPERTIES_INTERFACE,
                                                 QDBusConnection::systemBus());
    if(m_networkDbusInterface == nullptr) {
        qWarning()<< "m_netWorkDbusInterface init error";
    }
}

void WiFiShortcut::getUsedWIFIConnections()
{
    Q_EMIT toQueryUsedWifiConnect(m_networkDbusInterface);
}

void WiFiShortcut::updateIcon(QString wifiName)
{
    if (wifiName.isEmpty()) {
        if (m_wifiButtonIsOpen == true) {
            m_currentStatus.setName(tr("Not connected"));
            m_currentStatus.setColor(Color::ColorRole::HighLight);
        } else {
            m_currentStatus.setName(tr("Not connected"));
            m_currentStatus.setColor(Color::ColorRole::BaseColor);
        }
    } else {
        m_currentStatus.setName(wifiName);
        m_currentStatus.setColor(Color::ColorRole::HighLight);
    }
    emit statusChanged(m_currentStatus);
}

//启动失败使用命令行启动
bool WiFiShortcut::launchAppWithArguments(const QString& desktopFile,const QStringList& args)
{
    QDBusMessage message = QDBusMessage::createMethodCall(KYLIN_APP_MANAGER_NAME, KYLIN_APP_MANAGER_PATH, KYLIN_APP_MANAGER_INTERFACE, "LaunchAppWithArguments");
    message << desktopFile << args;
    return QDBusReply<bool>(QDBusConnection::sessionBus().call(message)).value();
}

void WiFiShortcut::kyWifiButtonActive()
{
    QDBusMessage message = QDBusMessage::createMethodCall(KYLIN_NETWORK_NAME, KYLIN_NETWORK_PATH,
                                                          KYLIN_NETWORK_INTERFACE, "setWirelessSwitchEnable");

    message << !m_wifiButtonIsOpen;
    QDBusConnection::sessionBus().call(message);
}

//启动网络界面
void WiFiShortcut::kywifibegin()
{
    QStringList args;
    args.append("--sw");
    if(!launchAppWithArguments("/etc/xdg/autostart/kylin-nm.desktop", args)) {
        QProcess::startDetached("kylin-nm", args);
    }
}

QString WiFiShortcut::pluginId()
{
    return QLatin1String("WiFi");
}

//事件处理
void WiFiShortcut::active(PluginMetaType::Action action)
{
    switch (action) {
    default:
    case PluginMetaType::Action::Click:
        //qDebug() << "点击事件";
        kyWifiButtonActive();
        break;
    case PluginMetaType::Action::LongClick:
        //qDebug() << "长按事件";
        break;
    case PluginMetaType::Action::MenuRequest:
        //qDebug() << "菜单事件";
        kywifibegin();
        break;
    }
}

const StatusInfo WiFiShortcut::currentStatus()
{
    return m_currentStatus;
}

//判断无线网卡是否可用
bool WiFiShortcut::isEnable()
{
    return m_wirelessDeviceIsEnable;
}

//网络连接状态改变
void WiFiShortcut::onPropertiesChanged(const QString &propertyType, const QVariantMap &propertyContent)
{
    if (propertyType == "org.freedesktop.NetworkManager") {
        for (const QString &keyStr : propertyContent.keys()) {
            if (keyStr == "WirelessEnabled") {
                m_wifiButtonIsOpen = propertyContent.value("WirelessEnabled").toBool();
                updateIcon("");
                continue;
//                qWarning()<<m_wifiButtonIsOpen;
            }
            //有关已连接网络变化的信号
            if ( (keyStr == "ActiveConnections") || (keyStr == "ActivatingConnection")){
                getUsedWIFIConnections();
                continue;
            }
            if (keyStr == "State"){
                int state = propertyContent.value("State").toInt();
                if (state >= 50 && state <= 70) {
                    getUsedWIFIConnections();
                }
            }
        }
    }
}

//网卡状态改变
void WiFiShortcut::onDevicestatusChanged()
{
    Q_EMIT toQueryDevice();
}

void WiFiShortcut::handleDeviceQuery(bool isUsed)
{
    m_wirelessDeviceIsEnable = isUsed;
    Q_EMIT enableStatusChanged(m_wirelessDeviceIsEnable);
}

void WiFiShortcut::handleUsedWifiConnect(QString wifiName)
{
    updateIcon(wifiName);
}

void WiFiShortcut::getButtonState()
{
    QDBusInterface interface( NETWORK_MANAGER_NAME,
                              NETWORK_MANAGER_PATH,
                              "org.freedesktop.DBus.Properties",
                              QDBusConnection::systemBus() );

    if (interface.isValid()) {
        QDBusReply<QVariant> replyEnabled = interface.call("Get", "org.freedesktop.NetworkManager", "WirelessEnabled");
        if (replyEnabled.isValid()) {
            m_wifiButtonIsOpen = replyEnabled.value().toBool();
        }
    }
}

QMap<PluginMetaType::SystemMode, PluginMetaData> WiFiShortcut::pluginMetaData()
{
    return m_metaData;
}

void WiFiShortcut::initMetaData()
{
    PluginMetaData pc {true, 0, PluginMetaType::PluginType::MenuButton};
    PluginMetaData tablet {true, 0, PluginMetaType::PluginType::MenuButton};
    m_metaData.insert(PluginMetaType::SystemMode::PC, pc);
    m_metaData.insert(PluginMetaType::SystemMode::Tablet, tablet);
}

WiFiShortcutPlugin::WiFiShortcutPlugin(QObject *parent) : UkuiShortcutPlugin(parent)
{

}

QStringList WiFiShortcutPlugin::translations()
{
    return {QStringLiteral("wifi-shortcut")};
}

Shortcut *WiFiShortcutPlugin::createShortcut()
{
    return new WiFiShortcut;
}
